
use serde::{Serialize, Deserialize};
use sha2::{Digest, Sha256};
use chrono::Utc;
use jsonwebtoken::{
    crypto::{sign, verify},
    decode, encode, Algorithm, DecodingKey, EncodingKey, Header, Validation,
};


pub fn set_panic_hook() {
    // When the `console_error_panic_hook` feature is enabled, we can call the
    // `set_panic_hook` function at least once during initialization, and then
    // we will get better error messages if our code ever panics.
    //
    // For more details see
    // https://github.com/rustwasm/console_error_panic_hook#readme
    #[cfg(feature = "console_error_panic_hook")]
    console_error_panic_hook::set_once();
}

const BEISEN_PUBLIC_KEY: &[u8; 458] = include_bytes!("cert/beisen.pub.100.pem");


/// 生成自定义Header
/// ```
/// let head = get_header();
/// println!("header: {:#?}", head);
/// ```
/// 
fn get_header() -> Header {

    let mut hasher = Sha256::default();
    hasher.update(BEISEN_PUBLIC_KEY);
    let kid = hasher.finalize();

    let kid_str = format!("{:x}", kid);

    let mut header = Header::new(Algorithm::RS256);

    header.kid = Some(kid_str);
    // println!("header: {:#?}",header);
    header
}

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct CustomClaims {
    appid: String,         
    uty: String,          
    url_type: String,          
    isv_type: u8,         
    vsn: u8,          
}

#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct Payload {
    iss: String,
    sub: String,
    aud: String,
    iat: i64,
    exp: i64,
    custom_claims: CustomClaims,
}

pub fn get_payload(
    iss: String,
    sub: String,
    aud: String,
    iat: i64,
    exp: i64,
    custom_claims: CustomClaims,
) -> Payload {
    let payload = Payload { iss, sub, aud, iat, exp, custom_claims };
    payload
}

#[test]
pub fn new_token() {
    let privkey_pem = include_bytes!("cert/beisen.pri.100.pem");

    let custom_claims = CustomClaims {
        appid: String::from("100"),         
        uty: String::from("123"),          
        url_type: String::from("0"),          
        isv_type: 0,         
        vsn: 1,  
    };

    let payload = Payload { 
        iss: String::from("asd"),
        sub: String::from("jiangkun"),
        aud: String::from("asa"),
        iat: Utc::now().timestamp(),
        exp: Utc::now().timestamp() + 10000,
        custom_claims,
    };

    let header = get_header();

    let key = EncodingKey::from_rsa_pem(privkey_pem).unwrap();

    let token = encode(&header,&payload, &key,).unwrap();

    println!("token: {:#?}", token);
}

#[test]
pub fn test() {
    println!("{:x}", sha2::Sha256::digest(BEISEN_PUBLIC_KEY));
}